package org.pockito.dctmpersistence;

import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.pockito.dmspersistence.DmsEntityManager;
import org.pockito.dmspersistence.DmsEntityManagerFactory;
import org.pockito.dmspersistence.DmsPersistenceException;

import com.documentum.com.DfClientX;
import com.documentum.fc.client.IDfClient;
import com.documentum.fc.client.IDfSessionManager;
import com.documentum.fc.common.DfException;
import com.documentum.fc.common.IDfLoginInfo;
import static org.pockito.dctmpersistence.PropertyConstants.*;

public class DmsEntityManagerFactoryImpl implements DmsEntityManagerFactory {

	/**
	 * Stores annotation info about our entities for easy retrieval when needed
	 */
	private AnnotationManager annotationManager;
	@SuppressWarnings("unused")
	private String persistenceUnitName;
	private Map<String, ?> props;

	public DmsEntityManagerFactoryImpl(String persistenceUnitName) {
		this(persistenceUnitName, null);
	}

	public DmsEntityManagerFactoryImpl(String persistenceUnitName,
			Map<String, ?> props) {
		this.persistenceUnitName = persistenceUnitName;
		this.props = props;
		this.annotationManager = new AnnotationManager();
	}

	public DmsEntityManager createDmsEntityManager() {
		return createDmsEntityManager(this.props);
	}

	public DmsEntityManager createDmsEntityManager(Map<String, ?> map) {
		try {
			IDfSessionManager sessionManager;
			DctmDriver dctmDriver = (DctmDriver) map.get(DriverClass);
			if (dctmDriver == null) {
				dctmDriver = getDctmDriver();
			}
			sessionManager = dctmDriver.getSessionManager();
			String username = (String) map.get(Username);
			if (StringUtils.isBlank(username)) throw new IllegalArgumentException("property 'username' is required");
			String password = (String) map.get(Password);
			String repository = (String) map.get(Repository);
			if (StringUtils.isBlank(repository)) throw new IllegalArgumentException("property 'repository' is required");
			
			// create an IDfLoginInfo object and set its fields
			DfClientX clientx = new DfClientX();
			IDfLoginInfo loginInfo = clientx.getLoginInfo();
			loginInfo.setUser(username);
			loginInfo.setPassword(password);

			// set single identity for all docbases
			sessionManager.setIdentity(repository, loginInfo);
			return new DmsEntityManagerDctm(this, map, sessionManager);
		} catch (Exception e) {
			throw new DmsPersistenceException(e);
		}
	}

	public void close() {
		// TODO close em

	}

	public boolean isOpen() {
		// TODO isOpen (em)
		return false;
	}

	protected AnnotationManager getAnnotationManager() {
		return annotationManager;
	}
	
	// TODO: should I use ThreadLocal to store the session manager ?
	public DctmDriver getDctmDriver() {
		return new DctmDriver() {
			
			public IDfSessionManager getSessionManager() throws DfException {
				// Create a client object using a factory method in DfClientX.

				DfClientX clientx = new DfClientX();
				IDfClient client = clientx.getLocalClient();

				// Call a factory method to create the session manager.

				IDfSessionManager sessionMgr = client.newSessionManager();
				return sessionMgr;
			}
		};
	}

}
